﻿using System;
using System.Diagnostics;
using System.Threading.Tasks;

namespace Devonline.Core
{
    public static class DelegateExtensions
    {
        /// <summary>
        /// 执行方法并返回执行时间
        /// </summary>
        /// <param name="action"></param>
        /// <returns></returns>
        public static TimeSpan WatchAction(this Action action)
        {
            if (action == null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            Stopwatch watch = Stopwatch.StartNew();
            action();
            return watch.Elapsed;
        }
        /// <summary>
        /// 执行方法并返回执行时间
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="action"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public static TimeSpan WatchAction<T>(this Action<T> action, T t)
        {
            if (action == null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            Stopwatch watch = Stopwatch.StartNew();
            action(t);
            return watch.Elapsed;
        }
        /// <summary>
        /// 执行任务并返回执行时间
        /// </summary>
        /// <param name="exec"></param>
        /// <returns></returns>
        public static async Task<TimeSpan> WatchActionAsync(this Func<Task> exec)
        {
            if (exec == null)
            {
                throw new ArgumentNullException(nameof(exec));
            }

            var watch = Stopwatch.StartNew();
            await exec().ConfigureAwait(false);
            return watch.Elapsed;
        }
        /// <summary>
        /// 执行任务并返回执行时间
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="task"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public static async Task<TimeSpan> WatchActionAsync<T>(this Func<T, Task> task, T t)
        {
            if (task == null)
            {
                throw new ArgumentNullException(nameof(task));
            }

            Stopwatch watch = Stopwatch.StartNew();
            await task(t).ConfigureAwait(true);
            return watch.Elapsed;
        }
    }
}
